package com.bootdo.ocr;

import com.google.common.collect.Maps;
import com.google.gson.annotations.Expose;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author  fk
 * @param <T> responseData
 * ocr返回结果基础类
 */
public abstract class OcrBaseResult<T> {

    private static final String BLANK_CHAR = " ";

    private static final String LINE_CHAR = "-";

    private static final int YEAR_LEN = 4;

    private static final int YEAR_1960 = 1960;

    private static final int YEAR_60 = 60;

    private static final String YEAR_19 = "19";

    private static final String YEAR_20 = "20";

    private static final int YEAR_2100 = 2100;


    private static final String ISO ="ISO";

    private static final String IEC ="IEC";
    /**
     * 校验是否是数字
     */
    protected static final String PATTERN_ISNUMBLE = "[0-9]*";
    /**
     * 校验是否为中文
     */
    protected static final String PATTERN_ISCHINESE = "[\u4e00-\u9fa5]";
    /**
     * 特舒符号转换成空格
     */
    protected Map<String, String> specialCharsToBlankMap = Maps.newHashMap();

    protected Map<String, String> patternSpecialCharMap = Maps.newHashMap();
    {
        specialCharsToBlankMap.put(" ","");
        specialCharsToBlankMap.put("—","");
        specialCharsToBlankMap.put("-","");
        specialCharsToBlankMap.put("/","");
        specialCharsToBlankMap.put("_", "");
        // 国标编码统一转换
        patternSpecialCharMap.put("-","/");
        patternSpecialCharMap.put("_","/");
    }
    /**
     * 去掉特殊字符
     * @param val
     * @return
     */
    protected String replacePatternBySpecialMap(String val){
        if (null != val) {
            for (String key : patternSpecialCharMap.keySet()) {
                val = val.replace(key, patternSpecialCharMap.get(key));
            }
        }
        return val;
    }

    /**
     * 去掉特殊字符
     * @param val
     * @return
     */
    protected String trimBySpecialMap(String val){
       if (null != val) {
           for (String key : specialCharsToBlankMap.keySet()) {
                val = val.replace(key, specialCharsToBlankMap.get(key));
           }
       }
        return val;
    }

    /**
     * 校验缺少的年月字段
     * 此处主要根据文件原始名称和 ocr获取的 code 进行比较
     * 1. 获取 当前文件的名称是否正确  MatchType
     * 2. 如果不正确 就自己根据规范拼接新的文件名称  correctFileName
     */
    protected MatchType validateOcrGbCodeCorrectFileName(String fileNameTemp ,String ocrGbCode, String pattern){
        final int fLen = fileNameTemp.length();
        final int ocrLen = ocrGbCode.length();
        this.correctFileName = this.fileName;
        if (fileNameTemp.equalsIgnoreCase(ocrGbCode)) {
            return MatchType.MATCH;
        }
        String filePrefixCode = null;
        String fileSuffixCode  = null;
        String ocrPrefixCode  = null;
        String ocrSuffixCode = null;
        fileSuffixCode = fileNameTemp.substring(fileNameTemp.length() - 2, fileNameTemp.length());
        ocrSuffixCode = ocrGbCode.substring(ocrGbCode.length() - 2, ocrGbCode.length());
        String differVal = null;
        if (fLen > ocrLen) {
            filePrefixCode = fileNameTemp.substring(0, fileNameTemp.length() - 4);
            ocrPrefixCode = ocrGbCode.substring(0, ocrGbCode.length() - 2);
            differVal = fileNameTemp.substring(fileNameTemp.length() - 4, fileNameTemp.length() - 2);
            this.correctFileName = ocrPrefixCode + LINE_CHAR +  differVal + ocrSuffixCode;
        } else {
            ocrPrefixCode  = ocrGbCode.substring(0, ocrGbCode.length() - 4);
            filePrefixCode = fileNameTemp.substring(0, fileNameTemp.length() - 2);
            differVal = ocrGbCode.substring(ocrGbCode.length() - 4, ocrGbCode.length() - 2);
        }
        if (Pattern.compile(PATTERN_ISNUMBLE).matcher(differVal).matches()
                && (Integer.valueOf(differVal) == 19 || Integer.valueOf(differVal) == 20)
                && filePrefixCode.equalsIgnoreCase(ocrPrefixCode)
                && ocrSuffixCode.equalsIgnoreCase(fileSuffixCode)) {
            this.correctFileName = this.fileName;
            return MatchType.PARTICAL;
        }
        /**
         * 没校验通过按照  编号来命名
         */
        this.correctFileName = fillNewFileName(ocrGbCode, pattern);
        return MatchType.NOTMATCH;
    }

    /**
     * 年份的处理
     * @param ocrGbCode 编码
     * @param pattern 编码匹配表达式
     * @return 文件名称
     */
    private String fillNewFileName(String ocrGbCode, String pattern) {
       String tempFileName =  ocrGbCode.replace(pattern, pattern + BLANK_CHAR);
        final int fileNameLen = tempFileName.length();
        if (fileNameLen > YEAR_LEN) {
            String year = tempFileName.substring(fileNameLen - 4, fileNameLen);
            /**
             * 校验是否为数值
             */
            if(Pattern.compile(PATTERN_ISNUMBLE).matcher(year).matches()) {
               int yearVal = Integer.valueOf(year);
               if (yearVal > YEAR_1960 && yearVal < YEAR_2100) {
                   tempFileName = tempFileName.replace(year, LINE_CHAR + year);
               }

            } else {
                year = tempFileName.substring(fileNameLen - 2, fileNameLen);
                if (Pattern.compile(PATTERN_ISNUMBLE).matcher(year).matches()) {
                    int yearVal = Integer.valueOf(year);
                    /**
                     * 1960 之后
                     */
                    if (yearVal > YEAR_60) {
                        tempFileName = tempFileName.replace( year, LINE_CHAR + YEAR_19 + year);
                    /**
                    *  2000 之后
                    */
                    } else {
                        tempFileName = tempFileName.replace(year, LINE_CHAR + YEAR_20 + year);
                    }
                }
            }
       }
       return tempFileName;
    }

    /**
     * 过滤掉 替换的编码
     * @param code 编码
     * @return 编码
     */
    protected String filterUpdateCode(String code) {
        if (code.indexOf("代替") >= 0 ) {
            String[] splitData = code.split("代替");
            if (splitData.length >= 2) {
                return  splitData[0];
            } else return null;
        }
        return code;
    }


    public  String matchWord(String line, Pattern pattern) {
        Matcher m = pattern.matcher(line);
        /**
         * 国标中不包含中文
         */
        if (isContainChinese(line)) {
            return "";
        }

        while (m.find()) {
            /**
             * 包含ISO
             */
            if (isContainISO(line)) {
                return line.split(ISO)[0];
            }
            if (isContainIEC(line)) {
                return line.split(IEC)[0];
            }
            return line;
        }
        return "";
    }

    /**
     * 中文内容检查
     * @param str
     * @return
     */
    public boolean isContainChinese(String str) {
        Pattern p = Pattern.compile(PATTERN_ISCHINESE);
        Matcher m = p.matcher(str);
        if (m.find()) {
             return true;
        }
        return false;
    }

    public boolean isContainISO(String str) {
        if (str.contains(ISO)) {
            return true;
        }
        return false;
    }

    public boolean isContainIEC(String str) {
        if (str.contains(IEC)) {
            return true;
        }
        return false;
    }
    @Expose(serialize = false)
    private T data;
    /**
     * 采集文字内容正则表达式
     */
   // protected Pattern pattern = Pattern.compile("^GB1");

    public abstract String fetchGbCode(String pattern);

    public void matchCode(String pattern) {
        this.ocrGbCode = trimBySpecialMap(fetchGbCode(pattern));
        this.setFileNameTemp(trimBySpecialMap(this.getFileName()));
        if (StringUtils.isNotEmpty(this.ocrGbCode)
                && StringUtils.isNotEmpty(getFileNameTemp())) {
            setMatchType(validateOcrGbCodeCorrectFileName(getFileNameTemp(), ocrGbCode, pattern));
        } else {
            /**
             *  不知道怎么处理
             *  1. 没有匹配上编码  或者内容的编码为空
             */
            setCorrectFilePath(getFilePath());
            setCorrectFileName(getFileName());
            setMatchType(MatchType.UNDO);
        }
    }

    private String filePath;

    private String fileName;

    private String fileNameTemp;

    protected String ocrGbCode;

    private MatchType matchType;

    private String correctFilePath;

    private String correctFileName;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }


    public String getFileNameTemp() {
        return fileNameTemp;
    }

    public void setFileNameTemp(String fileNameTemp) {
        this.fileNameTemp = fileNameTemp;
    }


    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getOcrGbCode() {
        return ocrGbCode;
    }

    public void setOcrGbCode(String ocrGbCode) {
        this.ocrGbCode = ocrGbCode;
    }

    public MatchType getMatchType() {
        return matchType;
    }


    public void setMatchType(MatchType matchType) {
        this.matchType = matchType;
    }

    public String getCorrectFileName() {
        return correctFileName;
    }

    public void setCorrectFileName(String correctFileName) {
        this.correctFileName = correctFileName;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public String getCorrectFilePath() {
        return correctFilePath;
    }

    public void setCorrectFilePath(String correctFilePath) {
        this.correctFilePath = correctFilePath;
    }
}
